// 1.类装饰器 ClassDecorator target 构造函数
// 2.属性装饰器 PropertyDecorator
// 3.参数装饰器 ParameterDecorator
// 4.方法装饰器 MethodDecorator PropertyDescriptor
// 5.装饰器工厂


// 类装饰器
/* const Base: ClassDecorator = (target) => {
    console.log(target); // // 可以拿到 target 构造函数,优势：不去破坏它自身原有的结构，去给它增加方法属性，起到一个修饰的作用（所以叫装饰器，或者修饰器）
    target.prototype.name = '小明'
    target.prototype.fn = () => {
        console.log('hello world!')
    }
}

@Base
class Http {
    ///....
}

const http = new Http() as any

http.fn()
console.log(http.name) */


// 装饰器工厂
/* const Base = (name: string) => {
    const fn: ClassDecorator = (target) => {
        console.log(target); // // 可以拿到 target 构造函数,优势：不去破坏它自身原有的结构，去给它增加方法属性，起到一个修饰的作用（所以叫装饰器，或者修饰器）
        target.prototype.name = name
        target.prototype.fn = () => {
            console.log(`hello ${name}!`)
        }
    }
    return fn
}

@Base('小红')
class Http {
    ///....
}

const http = new Http() as any

http.fn()
console.log(http.name) */

// 方法装饰器
/* import axios from "axios";
const Get = (url: string) => {
    const fn: MethodDecorator = (target, key, descriptor: PropertyDescriptor) => {
        console.log(target, key, descriptor); // 原型对象，方法名，描述符
        axios.get(url).then(res => {
            descriptor.value(res.data)
        })
    }
    return fn
}

class Http {
    @Get('https://www.baidu.com')
    getList(data: any) {
        console.log(data)
    }
    // @Post()
    // create() {

    // }

}

const http = new Http() as any */

// 参数装饰器 优先 方法装饰器
/* import 'reflect-metadata';
import axios from "axios";
let mockData:any = {
    result: {
        list: [1, 2, 3]
    }
}
const Get = (url: string) => {
    const fn: MethodDecorator = (target, propertyKey, descriptor: PropertyDescriptor) => {
        const key = Reflect.getMetadata('key', target)
        axios.get(url).then(res => {
            descriptor.value(key ? mockData[key] : mockData)
        })
    }
    return fn
}

const Result = (name: string) => {
    const fn: ParameterDecorator = (target, key, index) => {
        console.log(target, key, index); // 原型对象，方法名，参数所在位置
        Reflect.defineMetadata('key', name, target) // key,要存的值,原型对象，将数据存进元数据
    }
    return fn
}

class Http {
    @Get('https://www.baidu.com')
    getList(@Result('result') data: any) {
        console.log(data.list)
    }

}

const http = new Http() as any */


// 属性装饰器


const Name: PropertyDecorator = (target, key) => {
    console.log(target, key); // 原型对象,key
}
class Http {
    @Name
    name: string
    constructor() {
        this.name = '小明'
    }
}

const http = new Http() as any